home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / PostScript / Pencil / Source / PencilView.m < prev    next >
Encoding:
Text File  |  1995-06-12  |  31.4 KB  |  1,344 lines

  1. /*
  2. Pencil V1.0, Copyright 1994, 95 by Florian Marquardt.
  3. This program may be distributed under the terms of the GNU general
  4. public license (Start Pencil and select "Info>COPYING..." for a copy of the
  5. license).
  6. */
  7. #import "PencilView.h"
  8. #import "PencilGraphic.h"
  9. #import "MultipleSelection.h"
  10. #import "Group.h"
  11. #import "PencilImage.h"
  12. #import "PencilText.h"
  13.  
  14. #define EX te->location.x
  15. #define EY te->location.y
  16.  
  17. #define EDITED if(!edited) { edited=YES; [window setDocEdited:YES]; }
  18.  
  19. BOOL movementStatus=0;    // currently moving a graphic? (EPS images only redrawn when move finished)
  20. extern BOOL globalTermination;
  21. id globalText=nil; // used for drawing RichText
  22. NXStream *result=NULL; // used for passing results to the TCL interpreter (PencilTCLClient)
  23.  
  24. float *fpts=NULL;    // array for points for freehand drawing... global since there is only one mouse
  25. int maxfpts=200;    // arraysize=2*maxfpts*sizeof(float)
  26. float athresh, sumthresh;
  27.  
  28. @implementation PencilView
  29. - initFrame:(const NXRect *)re
  30. {
  31.     [super initFrame:re];
  32.     glist=[[List alloc] init];
  33.     scale=100;
  34.     if(fpts==NULL)
  35.     {    fpts=(float *)malloc(sizeof(float)*2*maxfpts);  }
  36.     if(!globalText)
  37.     {
  38.     globalText=[[Text alloc] init];
  39.     [globalText setMonoFont:NO];
  40.     [globalText setEditable:NO];
  41.     [globalText setSelectable:NO];
  42.     [globalText setFlipped:YES];
  43.     [globalText setClipping:NO];
  44.     }
  45.     if(flippedView=[[View alloc] initFrame:&bounds]) // for RichText editing
  46.     {
  47.         [flippedView setFlipped:YES];
  48.     }
  49.     return self;
  50. }
  51.  
  52. - (BOOL)acceptsFirstResponder { return YES; }
  53.  
  54. - awakeFromNib
  55. {
  56.     [window makeKeyAndOrderFront:self];
  57.     [inspector inspectForView:self];
  58.     return self;
  59. }
  60.  
  61. - free
  62. {
  63.     int i;
  64.  
  65.     if(glist) {
  66.     i=[glist count];
  67.     while(i--) [[glist objectAt:i] free];    
  68.     [glist free];
  69.     }
  70.     if(customDef)    free(customDef);
  71.     if(docname) free(docname);
  72.     return [super free];
  73. }
  74.  
  75. - (BOOL)acceptsFirstMouse { return YES; }
  76.  
  77. - drawSelf:(const NXRect *)re:(int)co
  78. {
  79.     int i,c; id g;
  80.  
  81.     if(!initialized || NXDrawingStatus!=NX_DRAWING)
  82.     {
  83.     char filename[300];
  84.     NXStream *stream;
  85.     char *buffer;
  86.     long l;
  87.  
  88.     strcpy(filename, [[NXBundle mainBundle] directory]);
  89.     strcat(filename, "/../pencilDefinitions.ps");
  90.     stream=NXMapFile(filename, NX_READONLY);
  91.     if(!stream)
  92.     {
  93.     strcpy(filename, [[NXBundle mainBundle] directory]);
  94.     strcat(filename, "/pencilDefinitions.ps");
  95.     stream=NXMapFile(filename, NX_READONLY);
  96.     }
  97.         if(stream)
  98.         {
  99.         NXSeek(stream,0,NX_FROMEND);
  100.         buffer=(char *)malloc(sizeof(char)*(l=NXTell(stream)+1));
  101.         NXSeek(stream,0,NX_FROMSTART);
  102.         NXRead(stream,buffer,l-1);
  103.         NXClose(stream);
  104.         buffer[l-1]=0;
  105.         DPSPrintf(DPSGetCurrentContext()," %s\n",buffer);
  106.         free(buffer);
  107.         }
  108.         else
  109.         {
  110.             NXRunAlertPanel("Alert", "Couldn't find pencilDefinitions.ps", "OK?!",NULL,NULL);
  111.             [NXApp terminate:self];
  112.         }
  113.     if(NXDrawingStatus==NX_DRAWING)
  114.     {
  115.     strcpy(filename, [[NXBundle mainBundle] directory]);
  116.     strcat(filename, "/../pencilControlProcDefinitions.ps");
  117.     stream=NXMapFile(filename, NX_READONLY);
  118.     if(!stream)
  119.     {
  120.     strcpy(filename, [[NXBundle mainBundle] directory]);
  121.     strcat(filename, "/pencilControlProcDefinitions.ps");
  122.     stream=NXMapFile(filename, NX_READONLY);
  123.     }
  124.         if(stream)
  125.         {
  126.         NXSeek(stream,0,NX_FROMEND);
  127.         buffer=(char *)malloc(sizeof(char)*(l=NXTell(stream)+1));
  128.         NXSeek(stream,0,NX_FROMSTART);
  129.         NXRead(stream,buffer,l-1);
  130.         NXClose(stream);
  131.         buffer[l-1]=0;
  132.         DPSPrintf(DPSGetCurrentContext()," %s\n",buffer);
  133.         free(buffer);
  134.         }
  135.         else
  136.         {
  137.             NXRunAlertPanel("Alert", "Couldn't find pencilControlProcDefinitions.ps", "OK?!",NULL,NULL);
  138.             [NXApp terminate:self];
  139.         }
  140.     }
  141.     else
  142.         if(customDef) DPSPrintf(DPSGetCurrentContext(), " %s\n ", customDef);
  143.         if(NXDrawingStatus==NX_DRAWING) initialized=YES;
  144.     }
  145.     [window disableFlushWindow];
  146.     PSsetgray(1);
  147.     if(re)    { NXRectClip(re); NXRectFill(re); } else NXRectFill(&bounds);
  148.     c=[glist count];
  149.     for(i=0;i<c;i++) if(![(g=[glist objectAt:i]) selected]) [g draw:re];
  150.     [window reenableFlushWindow];
  151.     return self;
  152. }
  153.  
  154. - displayCurrentGraphic
  155. {
  156.     if(currentGraphic)
  157.     {
  158.     [self lockFocus];
  159.         PSsetinstance(YES);
  160.         PSnewinstance();
  161.         [currentGraphic drawControl:NULL:curPt:500/scale];
  162.         PSsetinstance(NO);
  163.     [self unlockFocus];
  164.     }
  165.     return self;
  166. }
  167.  
  168. - displayWithCurrentGraphic
  169. {
  170.     [self display];
  171.     [self displayCurrentGraphic];
  172.     return self;
  173. }
  174.  
  175. - setCurrentGraphicAndDisplay:(id)gr
  176. {
  177.     currentGraphic=gr;
  178.     [self displayCurrentGraphic];
  179.     return self;
  180. }
  181.  
  182. #define IFCUR if(currentGraphic)
  183. #define CUR currentGraphic
  184.  
  185. const char *txtinit="/text (Text) def /fontsize 32 def /font (Helvetica) def";
  186.  
  187. #define ADJUST [self convertPoint:&te->location fromView:nil]
  188. - mouseDown:(NXEvent *)te
  189. {
  190.     // command-click: create new graphic
  191.     // click: if currentGraphic selected: select/move pts or move graphic
  192.     //         if not: try to select/move graphic
  193.     // control-click: rotate
  194.  
  195.     if(!editingRichText)
  196.     {
  197.     if(te->flags & NX_COMMANDMASK) // create
  198.     {
  199.         char *mname; NXColor c1; NXColor c2; float lw; char *dm; char *fm; char *sm; char *ud; NXRect rec; 
  200.  
  201.         EDITED;
  202.         IFCUR { [CUR calculateBoundingBox:self]; [CUR giveBounds:&rec]; [CUR select:NO];   }
  203.             else    rec=bounds;
  204.         [inspector giveSettings:&mname:&c1:&c2:&lw:&dm:&fm:&sm:&ud];
  205.         if(!currentGraphic && !strncmp(mname,"charP", 5))
  206.         {
  207.                     [inspector setUserDef:txtinit];
  208.                     ud=txtinit;
  209.         }
  210.         if(!strcmp(mname,"RT"))
  211.             [glist addObject:CUR=[[[PencilText alloc] init] initWithSettings:mname:c1:c2:lw:dm:fm:sm:ud]];
  212.         else
  213.             [glist addObject:CUR=[[[PencilGraphic alloc] init] initWithSettings:mname:c1:c2:lw:dm:fm:sm:ud]];
  214.         curGrPos=[glist count]-1;
  215.         [CUR select:YES];
  216.         [self display:&rec:1];
  217.         // if RichText desired
  218.         if(!strcmp(mname,"RT"))
  219.         {
  220.             editingRichText=YES;
  221.             [self addSubview:flippedView];
  222.             [flippedView setFrame:&bounds];
  223.             [CUR editText:te:self:flippedView];
  224.         }
  225.         else
  226.         {
  227.         if([[[[[inspector creationType] target] itemList] selectedCell] tag]==1)
  228.         {
  229.             athresh=[[ inspector athreshField] floatValue];
  230.             sumthresh=[[inspector sthreshField] floatValue];
  231.             if(athresh<.1) athresh=1.5;
  232.             if(sumthresh<.1)    sumthresh=.9;
  233.             [CUR createPolyFreehand:te:&curPt:self:500/scale];
  234.         }
  235.         else
  236.         {
  237.             [CUR create:te:&curPt:self:500/scale];
  238.         }
  239.         }
  240.     }
  241.     else    // select graphic/point, move point
  242.     {
  243.         [self convertPoint:&te->location fromView:nil];
  244.  
  245.         IFCUR
  246.         {
  247.             if([CUR isMemberOf:[PencilText class]])
  248.             {
  249.                 if(te->data.mouse.click==2)                {
  250.                     editingRichText=YES;
  251.                     EDITED;
  252.                     [self addSubview:flippedView];
  253.                     [flippedView setFrame:&bounds];
  254.                     [CUR editText:te:self:flippedView];
  255.                     return self;
  256.                 }
  257.             }
  258.  
  259.             if(!(te->flags & NX_CONTROLMASK)) { // not rotating/scaling
  260.             // select pt, move it
  261.             if([CUR move:te:&curPt:self:500/scale])    { EDITED; return self; }
  262.             }
  263.         }
  264.  
  265.         {    // select graphic
  266.             int i, selCount=0;
  267.             id curcur=currentGraphic;
  268.  
  269.             if(!CUR && !(te->flags & NX_CONTROLMASK)) te->flags&=(~NX_SHIFTMASK);
  270.             if(CUR && ![CUR isMemberOf:[MultipleSelection class]] && (!(te->flags&NX_SHIFTMASK) || (te->flags & NX_CONTROLMASK)))
  271.             {
  272.             if((te->flags & NX_ALTERNATEMASK) && !(te->flags & NX_CONTROLMASK)) i=curGrPos; else i=curGrPos+1;
  273.             while(i--) if([[glist objectAt:i] selected:te:&curPt:self]) break;
  274.             if(i<0)
  275.             {
  276.                 i=[glist count];
  277.                 while(--i>curGrPos) if([[glist objectAt:i] selected:te:&curPt:self]) break;
  278.                 if(i<=curGrPos)    i=-1;
  279.             }
  280.             }
  281.             else
  282.             {
  283.                 id g;
  284.  
  285.                 i=[glist count]; while(i--) { if([g=[glist objectAt:i] selected]) ++selCount; if([g selected:te:&curPt:self]) break; }
  286.             }
  287.             if(i>=0)
  288.             {
  289.                 char *name; NXColor c1; NXColor c2; float lw; char *dm, *fm, *sm, *ud;
  290.                 NXRect rec; BOOL multipleSelChanged=NO;
  291.  
  292.                 if((te->flags & NX_SHIFTMASK) && !(te->flags & NX_CONTROLMASK)) // multiple selection
  293.                 {
  294.                 if(![[glist objectAt:i] selected])
  295.                 {
  296.                     if(!CUR || ![CUR isMemberOf:[MultipleSelection class]])
  297.                     {
  298.                         IFCUR {
  299.                         CUR=[[MultipleSelection alloc] initWithGraphic:CUR];
  300.                         [CUR addToSelection:[[glist objectAt:i] select:YES] posFromEnd:selCount];
  301.                         }
  302.                         else
  303.                         {
  304.                             CUR=[[MultipleSelection alloc] initWithGraphic:[[glist objectAt:i] select:YES]];
  305.                         }
  306.                     }
  307.                     else
  308.                         [CUR addToSelection:[[glist objectAt:i] select:YES] posFromEnd:selCount];
  309.                     multipleSelChanged=YES;
  310.                 }
  311.                 }
  312.                 else
  313.                 {
  314.                     if(!CUR || ![CUR isMemberOf:[MultipleSelection class]] || ![[glist objectAt:i] selected])
  315.                     {
  316.                     CUR=[glist objectAt:i];
  317.                     curGrPos=i;
  318.                     [CUR select:YES];
  319.                     }
  320.                 }
  321.                 if(curcur!=CUR && curcur!=nil && (!multipleSelChanged || ![CUR partOfSelection:curcur]))
  322.                 {
  323.                     [curcur calculateBoundingBox:self];
  324.                     [curcur giveBounds:&rec];
  325.                     [curcur select:NO];
  326.                     [self display:&rec:1];
  327.                 }
  328.                 if(curcur!=CUR   || multipleSelChanged)
  329.                 {
  330.                     [CUR calculateBoundingBox:self];
  331.                     [CUR giveBounds:&rec];
  332.                     [self display:&rec:1];
  333.                 }
  334.                 [self lockFocus];
  335.                 PSsetinstance(YES);
  336.                 if(curcur!=CUR   || multipleSelChanged)
  337.                 {
  338.                 PSnewinstance();
  339.                 [currentGraphic drawControl:NULL:curPt:500/scale];
  340.                 }
  341.                 if(curcur!=CUR)
  342.                 {
  343.                 [CUR giveSettings:&name:&c1:&c2:&lw:&dm:&fm:&sm:&ud];
  344.                 [inspector takeSettings:name:c1:c2:lw:dm:fm:sm:ud];
  345.                 }
  346.                 {    // moving/rotating/scaling the selection
  347.     
  348.             if(te->flags & NX_CONTROLMASK) // rotate or scale
  349.                 {
  350.             if(te->flags & NX_SHIFTMASK) // scale
  351.             {
  352.      int    oldMask;
  353.     BOOL shouldLoop=YES;
  354.     float dx,dy, oldscalex=1, oldscaley=1, newscalex, newscaley;
  355.     NXEvent thisEvent;
  356.     
  357.     EDITED;
  358.     
  359.         oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];
  360.  
  361.     dx=te->location.x; dy=te->location.y;
  362.  
  363.     while (shouldLoop) {
  364.         do {
  365.     te = [NXApp getNextEvent:(NX_LMOUSEUPMASK |
  366.                                          NX_LMOUSEDRAGGEDMASK)];
  367.         } while(te->type==NX_LMOUSEDRAGGED && ([NXApp peekNextEvent:NX_LMOUSEDRAGGEDMASK into:&thisEvent]));
  368.  
  369.        ADJUST;
  370.     newscalex=(EX-dx)/20+1;
  371.     if(!(te->flags & NX_ALTERNATEMASK)) newscaley=newscalex; else newscaley=(EY-dy)/20+1;
  372.     if(fabs(newscalex)<1e-3) newscalex=1e-3;
  373.     if(fabs(newscaley)<1e-3) newscaley=1e-3;
  374.     [CUR scaleCenter:dx:dy by:newscalex/oldscalex:newscaley/oldscaley];
  375.     oldscalex=newscalex;
  376.     oldscaley=newscaley;
  377.     PSnewinstance();
  378.     [CUR drawControl:NULL:curPt:500/scale];
  379.     PSflushgraphics();
  380.     NXPing();
  381.     if(te->type==NX_LMOUSEUP) shouldLoop=NO;
  382.     }
  383.     PSnewinstance();
  384.     [CUR drawControl:NULL:curPt:500/scale];
  385.     PSflushgraphics();
  386.     NXPing();
  387.     PSsetinstance(NO);
  388.     [self unlockFocus];
  389.     [window setEventMask:oldMask];
  390.     return self;
  391.             }
  392.             else
  393.             {
  394.       int    oldMask;
  395.     BOOL shouldLoop=YES;
  396.     float dx,dy;
  397.     BOOL placingHorizontal=YES;
  398.     NXPoint pt0, pt1;
  399.     NXEvent thisEvent;
  400.     
  401.         oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];
  402.  
  403.     dx=te->location.x; dy=te->location.y;
  404.  
  405.  
  406.     while (shouldLoop) {
  407.             do {
  408.     te = [NXApp getNextEvent:(NX_LMOUSEUPMASK |
  409.                                          NX_LMOUSEDRAGGEDMASK | NX_LMOUSEDOWNMASK)];
  410.         } while(te->type==NX_LMOUSEDRAGGED && ([NXApp peekNextEvent:NX_LMOUSEDRAGGEDMASK into:&thisEvent]));
  411.  
  412.        ADJUST;
  413.         if(placingHorizontal)
  414.         {
  415.             PSnewinstance();
  416.             [CUR drawControl:NULL:curPt:500/scale];
  417.             PSsetgray(0);
  418.             PSmoveto(dx-5,dy);
  419.             PSrlineto(10,0); PSstroke();
  420.             PSmoveto(dx, dy-5);
  421.             PSrlineto(0,10); PSstroke();
  422.             PSmoveto(dx,dy);
  423.             PSlineto(te->location.x, te->location.y);
  424.             PSstroke();
  425.             PSflushgraphics();
  426.             NXPing();
  427.         }
  428.         else
  429.         {
  430.             [CUR rotateAroundCenter:dx:dy fromPoint:&pt1 toPoint:&te->location];
  431.             pt1=te->location;
  432.             PSnewinstance();
  433.             [CUR drawControl:NULL:curPt:500/scale];
  434.             PSsetgray(.5);
  435.             PSmoveto(dx-5,dy);
  436.             PSrlineto(10,0); PSstroke();
  437.             PSmoveto(dx, dy-5);
  438.             PSrlineto(0,10); PSstroke();
  439.             PSmoveto(dx,dy);
  440.             PSlineto(pt0.x, pt0.y);
  441.             PSstroke();
  442.             PSflushgraphics();
  443.             NXPing();
  444.         }
  445.         if(te->type==NX_LMOUSEUP)
  446.         {
  447.             if(placingHorizontal)
  448.             {
  449.                 placingHorizontal=NO;
  450.                 pt0=pt1=te->location;
  451.                 if(pt0.x==dx && pt0.y==dy) { pt0.x+=30; pt1=pt0; }
  452.             }
  453.             else
  454.                 shouldLoop=NO;
  455.         }
  456.     }
  457.     PSnewinstance();
  458.     [CUR drawControl:NULL:curPt:500/scale];
  459.     PSflushgraphics();
  460.     NXPing();
  461.     PSsetinstance(NO);
  462.     [self unlockFocus];
  463.     [window setEventMask:oldMask];
  464.     return self;
  465. }
  466. }
  467. else
  468. {
  469.       int    oldMask;
  470.     BOOL shouldLoop=YES;
  471.     float dx,dy;
  472.     NXEvent thisEvent;
  473.     
  474.         oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];
  475.  
  476.     dx=te->location.x; dy=te->location.y;
  477.  
  478.     while (shouldLoop) {
  479.         do {
  480.     te = [NXApp getNextEvent:(NX_LMOUSEUPMASK |
  481.                                          NX_LMOUSEDRAGGEDMASK)];
  482.         } while(te->type==NX_LMOUSEDRAGGED && ([NXApp peekNextEvent:NX_LMOUSEDRAGGEDMASK into:&thisEvent]));
  483.  
  484.        ADJUST;
  485.     if(EX!=dx || EY!=dy)
  486.     {
  487.     movementStatus=1;
  488.     EDITED;
  489.     [CUR addTranslation:EX-dx:EY-dy];
  490.     dx=EX; dy=EY;
  491.     PSnewinstance();
  492.     [CUR drawControl:NULL:curPt:500/scale];
  493.     PSflushgraphics();
  494.     NXPing();
  495.     }
  496.     if(te->type==NX_LMOUSEUP)
  497.         shouldLoop=NO; 
  498.  
  499.     }
  500.         if(movementStatus) {
  501.         movementStatus=0;
  502.         [CUR drawIfNeeded:NULL:curPt:500/scale];
  503.     }
  504.     PSsetinstance(NO);
  505.     [self unlockFocus];
  506.     [window setEventMask:oldMask];
  507.     }
  508. }
  509.             }
  510.             else        // no graphic selected
  511.             {
  512.                 IFCUR
  513.                 {
  514.                     NXRect rec;
  515.  
  516.                     [CUR calculateBoundingBox:self];
  517.                     [CUR giveBounds:&rec];
  518.                     [CUR select:NO];
  519.                     CUR=nil; curGrPos=-1;
  520.                     [self display:&rec:1];
  521.                     [self lockFocus]; PSnewinstance(); [self unlockFocus];
  522.                     [inspector clearUserDef:nil];
  523.                 }
  524.                 // drag selection
  525. {      int    oldMask;
  526.     BOOL shouldLoop=YES;
  527.     float dx,dy;
  528.     int c=[glist count];
  529.     NXRect theSel, thebounds;
  530.  
  531.         oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];
  532.  
  533.     dx=te->location.x; dy=te->location.y;
  534.  
  535.     [self lockFocus];
  536.     PSsetinstance(YES);
  537.     
  538.     while (shouldLoop) {
  539.         te = [NXApp getNextEvent:(NX_LMOUSEUPMASK |
  540.                                          NX_LMOUSEDRAGGEDMASK)];
  541.  
  542.        ADJUST;
  543.     if(EX!=dx || EY!=dy)
  544.     {
  545.     PSnewinstance();
  546.     PSsetgray(.5);
  547.     PSrectstroke(dx,dy,EX-dx,EY-dy);
  548.     PSflushgraphics();
  549.     }
  550.     if(te->type==NX_LMOUSEUP)
  551.         shouldLoop=NO; 
  552.  
  553.     }
  554.     PSsetinstance(NO);
  555.     PSnewinstance();
  556.     [self unlockFocus];
  557.     [window setEventMask:oldMask];
  558.     
  559.     if(dx<EX) { theSel.origin.x=dx;  theSel.size.width=EX-dx; } else { theSel.origin.x=EX; theSel.size.width=dx-EX; }
  560.     if(dy<EY) { theSel.origin.y=dy; theSel.size.height=EY-dy; } else { theSel.origin.y=EY; theSel.size.height=dy-EY; }
  561.     if(theSel.size.width!=0 && theSel.size.height!=0)
  562.     {
  563.     for(i=0;i<c;i++)    {
  564.     [[glist objectAt:i] giveBounds:&thebounds];
  565.     if(NXIntersectsRect(&theSel, &thebounds))
  566.     {
  567.         IFCUR { [CUR addToSelection:[[glist objectAt:i] select:YES] posFromEnd:0]; }
  568.         else
  569.         {    [CUR=[MultipleSelection alloc] initWithGraphic:[[glist objectAt:i] select:YES]];
  570.          }
  571.     }
  572.     }
  573.     IFCUR {
  574.     [CUR calculateBoundingBox:self];
  575.     [CUR giveBounds:&thebounds];
  576.     [self display:&thebounds:1];
  577.     [self displayCurrentGraphic];
  578.     }
  579.     }
  580. }
  581.             }
  582.         }
  583.     }
  584.     }
  585.     else
  586.         [window endEditingFor:self];
  587.     return self;
  588. }
  589.  
  590. - (BOOL)makeGroup
  591. {
  592.     id oldcur;
  593.  
  594.     if(CUR && [CUR isMemberOf:[MultipleSelection class]])
  595.     {
  596.     EDITED;
  597.     oldcur=CUR;
  598.     [glist addObject:CUR=[[[Group alloc] initEmpty] select:YES]];
  599.     [oldcur moveElementsFrom:glist to:[CUR slist]];
  600.     [oldcur select:NO];
  601.     return YES;
  602.     }
  603.     else
  604.         return NO;
  605. }
  606.  
  607. - ungroup
  608. {
  609.     if(CUR && [CUR isKindOf:[Group class]])
  610.     {
  611.         id sl, old;
  612.         int i,c,pos;
  613.     
  614.         EDITED;
  615.         sl=[old=CUR slist];
  616.         c=[sl count];
  617.         pos=[glist indexOf:CUR];
  618.         [glist removeObject:CUR];
  619.         CUR=[[MultipleSelection alloc] initEmpty];
  620.         [old addElementsTo:[CUR slist]];
  621.         for(i=0;i<c;i++)    [glist insertObject:[sl objectAt:i] at:pos+i];
  622.         [old freeLeaveObjects];
  623.     }
  624.     return self;
  625. }
  626.  
  627. - ungroup:sender
  628. {
  629.     [self ungroup];
  630.     [self displayWithCurrentGraphic];
  631.     return self;
  632. }
  633.  
  634. - makeStandardGroup:sender
  635. {
  636.     if([self makeGroup])
  637.     {
  638.         [CUR setGroupType:PENCIL_STANDARD_GROUP];
  639.         [self displayCurrentGraphic];
  640.     }
  641.     return self;
  642. }
  643.  
  644. - makeClipGroup:sender
  645. {
  646.     if([self makeGroup])
  647.     {
  648.         [CUR setGroupType:PENCIL_CLIP_GROUP];
  649.         [self displayCurrentGraphic];
  650.     }
  651.     return self;
  652. }
  653.  
  654. - deselectAll:sender
  655. {
  656.                 IFCUR
  657.                 {
  658.                     NXRect rec;
  659.  
  660.                     [CUR calculateBoundingBox:self];
  661.                     [CUR giveBounds:&rec];
  662.                     [CUR select:NO];
  663.                     CUR=nil; curGrPos=-1; 
  664.                     [self display:&rec:1];
  665.                     [self lockFocus]; PSnewinstance(); [self unlockFocus];
  666.                     [inspector clearUserDef:nil];
  667.                 }
  668.     return self;
  669. }
  670. - selectAll:sender
  671. {
  672.     int c=[glist count], i;
  673.     NXRect thebounds;
  674.  
  675.     IFCUR { [CUR select:NO]; CUR=nil; curGrPos=-1; }
  676.     for(i=0;i<c;i++)    {
  677.         IFCUR { [CUR addToSelection:[[glist objectAt:i] select:YES] posFromEnd:0]; }
  678.         else
  679.         {    [CUR=[MultipleSelection alloc] initWithGraphic:[[glist objectAt:i] select:YES]];  }
  680.     }
  681.     [CUR calculateBoundingBox:self];
  682.     [CUR giveBounds:&thebounds];
  683.     NXIntersectionRect(&bounds,&thebounds);
  684.     [self display:&thebounds:1];
  685.     [self displayCurrentGraphic];
  686.     return self;
  687. }
  688. - setMethodname:(char*)name { IFCUR { [CUR setMethodname:name]; EDITED; } return [self displayCurrentGraphic]; }
  689. - setDrawingMethod:(char *)name { IFCUR  { [CUR setDrawingMethod:name]; EDITED; } return [self displayCurrentGraphic]; }
  690. - setStrokeMethod:(char *)name { IFCUR { [CUR setStrokeMethod:name]; EDITED; } return [self displayCurrentGraphic]; }
  691. - setFillMethod:(char *)name { IFCUR { [CUR setFillMethod:name]; EDITED; } return [self displayCurrentGraphic]; }
  692. - setSpecialAttributes:(char *)name { IFCUR { [CUR setSpecialAttributes:name]; EDITED; } return [self displayCurrentGraphic]; }
  693. - setColor1:(NXColor)col { IFCUR { [CUR setColor1:col]; EDITED; } return [self displayCurrentGraphic];}
  694. - setColor2:(NXColor)col { IFCUR { [CUR setColor2:col]; EDITED; } return [self displayCurrentGraphic]; }
  695. - setLineWidth:(float)lw { IFCUR { [CUR setLineWidth:lw]; EDITED; } return [self displayCurrentGraphic]; }
  696. - changeScale:sender
  697. {
  698.     float sc;
  699.  
  700.     sc=atoi([[sender selectedCell] title]);
  701.     if(sc>0)
  702.     {
  703.     float x,y,w,h;
  704.     x=bounds.origin.x;
  705.     y=bounds.origin.y;
  706.     w=bounds.size.width;
  707.     h=bounds.size.height;
  708.     [self scale:sc/scale:sc/scale];
  709.     [self translate: bounds.origin.x-(x+w/2-bounds.size.width/2):bounds.origin.y-(y+h/2-bounds.size.height/2)];
  710.     scale=sc;
  711.     [self display];
  712.     [self displayCurrentGraphic];
  713.     }
  714.     return self;
  715. }
  716. - scroll:sender
  717. {
  718.     switch([sender tag])
  719.     {
  720.     case 0: [self translate:0:bounds.size.height*[scrollFactor floatValue]]; break;
  721.     case 1: [self translate:0:bounds.size.height*(-[scrollFactor floatValue])]; break;
  722.     case 2: [self translate:bounds.size.width*(-[scrollFactor floatValue]):0]; break;
  723.     case 3: [self translate:bounds.size.width*[scrollFactor floatValue]:0]; break;
  724.     }
  725.     [self display];
  726.     [self displayCurrentGraphic];
  727.     return self;
  728. }
  729. - toFront:sender
  730. {
  731.     IFCUR
  732.     {
  733.         EDITED;
  734.         if([CUR isMemberOf:[MultipleSelection class]])
  735.             [CUR toFrontIn:glist];
  736.         else
  737.         {
  738.         if(curGrPos!=[glist count]-1)
  739.         {
  740.             [glist removeObjectAt:curGrPos];
  741.             [glist addObject:currentGraphic];
  742.         }
  743.         }
  744.     }
  745.     return self;
  746. }
  747. - toBack:sender
  748. {
  749.     IFCUR
  750.     {
  751.         EDITED;
  752.         if([CUR isMemberOf:[MultipleSelection class]])
  753.             [CUR toBackIn:glist];
  754.         else
  755.         {
  756.         if(curGrPos!=0)
  757.         {
  758.             [glist removeObjectAt:curGrPos];
  759.             [glist insertObject:currentGraphic at:0];
  760.         }
  761.         }
  762.     }
  763.     return self;
  764. }
  765. - insertPoint:sender
  766. {
  767.     IFCUR    {    EDITED; [(PencilGraphic *)currentGraphic insertPoint:&curPt]; [self displayCurrentGraphic]; }
  768.     return self;
  769. }
  770. - insertNextPoint:sender
  771. {
  772.     IFCUR    {    EDITED; [(PencilGraphic *)currentGraphic insertNextPoint:&curPt]; [self displayCurrentGraphic]; }
  773.     return self;
  774. }
  775. - deletePoint:sender
  776. {
  777.     IFCUR    {    EDITED; [(PencilGraphic *)currentGraphic deletePoint:&curPt]; [self displayCurrentGraphic]; }
  778.     return self;
  779. }
  780.  
  781. - insertThreePoints:sender
  782. {
  783.     IFCUR    {    EDITED; [(PencilGraphic *)currentGraphic insertThreePoints:&curPt]; [self displayCurrentGraphic]; }
  784.     return self;
  785. }
  786. - alignThreePoints:sender
  787. {
  788.     IFCUR    {    EDITED; [(PencilGraphic *)currentGraphic alignThreePoints:&curPt]; [self displayCurrentGraphic]; }
  789.     return self;
  790. }
  791.  
  792. - keyDown:(NXEvent *)te
  793. {
  794.     if(te->data.key.charCode==127)
  795.         [self deleteGraphic:self];
  796.     else
  797.     {
  798.     switch((char)(te->data.key.charCode))
  799.     {
  800.     case '8': [self translate:0:bounds.size.height*[scrollFactor floatValue]]; break;
  801.     case '2': [self translate:0:bounds.size.height*(-[scrollFactor floatValue])]; break;
  802.     case '4': [self translate:bounds.size.width*(-[scrollFactor floatValue]):0]; break;
  803.     case '6': [self translate:bounds.size.width*[scrollFactor floatValue]:0]; break;
  804.     case ' ' :
  805.     case 13: return [self paste:self:YES]; break;
  806.     }
  807.     [self display];
  808.     [self displayCurrentGraphic];
  809.     }
  810.     return self;
  811. }
  812.  
  813. - deleteGraphic:sender
  814. {
  815.     IFCUR {            EDITED; if([CUR isMemberOf:[MultipleSelection class]])
  816.  [CUR deleteThemIn:glist]; else [glist removeObjectAt:curGrPos]; curGrPos=-1; currentGraphic=nil; [self lockFocus]; PSnewinstance(); [self unlockFocus];  }
  817.     return self;
  818. }
  819.  
  820. - writeDoc:(NXTypedStream *)stream
  821. {
  822.     int n, i;
  823.     NXRect wframe;
  824.  
  825.     [window getFrame:&wframe];
  826.     NXWriteRect(stream, &wframe);
  827.     NXWriteRect(stream, &bounds);
  828.     NXWriteRect(stream, &frame);
  829.     n=[glist count];
  830.     NXWriteTypes(stream,"f*i",&scale, &customDef, &n);
  831.     for(i=0;i<n;i++)
  832.         NXWriteRootObject(stream, [glist objectAt:i]);
  833.     return self;
  834. }
  835.  
  836. - readDoc:(NXTypedStream *)stream
  837. {
  838.     int n;
  839.     NXRect nbounds, nframe, wframe;
  840.  
  841.     NXReadRect(stream, &wframe);
  842.     NXReadRect(stream, &nbounds);
  843.     NXReadRect(stream, &nframe);
  844.     NXReadTypes(stream,"f*i",&scale, &customDef,&n);
  845.     [glist=[List alloc] setAvailableCapacity:n];
  846.     while(n--) [glist addObject:NXReadObject(stream)];
  847.     [window placeWindow:&wframe];
  848.     // [self setFrame:&nframe];
  849.     [self setDrawSize:nbounds.size.width:nbounds.size.height];
  850.     [self setDrawOrigin:nbounds.origin.x: nbounds.origin.y];
  851.     return self;
  852. }
  853.  
  854. - doSave:(char *)filename
  855. {
  856.     NXTypedStream *st;
  857.     
  858.     if(st=NXOpenTypedStreamForFile(filename, NX_WRITEONLY))
  859.     {
  860.     edited=NO;
  861.     [window setDocEdited:NO];
  862.     [self writeDoc:st];
  863.     NXCloseTypedStream(st);
  864.     }
  865.     return self;
  866. }
  867.  
  868. - saveAs:sender
  869. {
  870.     [[SavePanel new] setRequiredFileType:"pencil"];
  871.     if([[SavePanel new] runModal]==NX_OKTAG)
  872.     {
  873.     if([[SavePanel new] filename])
  874.     {
  875.     if(docname) free(docname);
  876.     docname=(char *)malloc(sizeof(char)*(strlen([[SavePanel new] filename])+1));
  877.     strcpy(docname, [[SavePanel new] filename]);
  878.     [window setTitleAsFilename:docname];
  879.     [self doSave:docname];
  880.     }
  881.     }
  882.     return self;
  883. }
  884.  
  885. - save:sender
  886. {
  887.     if(docname) [self doSave:docname]; else [self saveAs:sender];
  888.     return self;
  889. }
  890.  
  891. - readFromFilename:(char *)name
  892. {
  893.     int i;
  894.     NXStream *st;
  895.     
  896.     if(st=NXOpenTypedStreamForFile(name, NX_READONLY))
  897.     {
  898.     if(glist) {
  899.     i=[glist count];
  900.     while(i--) [[glist objectAt:i] free];    
  901.     [glist free];
  902.     }
  903.     if(customDef)    free(customDef);
  904.     if(docname) free(docname);
  905.     docname=(char *)malloc(sizeof(char)*(strlen(name)+1));
  906.     strcpy(docname, name);
  907.     [window setTitleAsFilename:docname];
  908.     [self readDoc:st];
  909.     NXCloseTypedStream(st);
  910.     [self sendCustom];
  911.     // [self display];
  912.     [window display];
  913.     }
  914.     return self;
  915. }
  916.  
  917. - windowDidBecomeMain:sender
  918. {
  919.     char *name; NXColor c1; NXColor c2; float lw; char *dm, *fm, *sm, *ud;
  920.  
  921.     [inspector inspectForView:self];
  922.     IFCUR {                 [CUR giveSettings:&name:&c1:&c2:&lw:&dm:&fm:&sm:&ud];
  923.                 [inspector takeSettings:name:c1:c2:lw:dm:fm:sm:ud];
  924. }
  925.     return self;
  926. }
  927.  
  928. - windowWillClose:sender
  929. {
  930.     int ch;
  931.  
  932.     if(!globalTermination)
  933.     {
  934.     if(edited)
  935.     {
  936.     if(docname)
  937.         ch=NXRunAlertPanel("Close Document", "Do you want to save \"%s\" before closing it?", "Save","Don't save","Cancel", docname);
  938.     else
  939.         ch=NXRunAlertPanel("Close Document", "Do you want to save the yet unnamed document before closing it?", "Save","Don't save","Cancel");
  940.     switch(ch)
  941.     {
  942.     case 0: [inspector viewVanished:self]; return self;
  943.     case 1: [self save:self]; [inspector viewVanished:self]; return self;
  944.     case -1: return nil;
  945.     }
  946.     }
  947.     }
  948.     else
  949.     {
  950.     if(edited)
  951.     {
  952.     if(docname)
  953.         ch=NXRunAlertPanel("Close Document", "Do you want to save \"%s\" before quitting?", "Save","Don't save","Cancel", docname);
  954.     else
  955.         ch=NXRunAlertPanel("Close Document", "Do you want to save the yet unnamed document before quitting?", "Save","Don't save","Cancel");
  956.     switch(ch)
  957.     {
  958.     case 0: [inspector viewVanished:self]; return self;
  959.     case 1: [self save:self]; [inspector viewVanished:self]; return self;
  960.     case -1: globalTermination=NO; return nil;
  961.     }
  962.     }
  963.     }
  964.     [inspector viewVanished:self]; return self;
  965. }
  966.  
  967. -copy:sender
  968. {
  969.     const char  *const types[1] = {"PencilPBoardType"};
  970.     id           pb = [Pasteboard new];
  971.     char        *data;
  972.     int          length;
  973.  
  974.     if(currentGraphic)
  975.     {
  976.     [CUR calculateBoundingBox:self];
  977.     [pb declareTypes:types num:1 owner:nil];
  978.     data = NXWriteRootObjectToBuffer(currentGraphic, &length);
  979.     [pb writeType:types[0] data:data length:length];
  980.     NXFreeObjectBuffer(data, length);
  981.     }  
  982.   return self;
  983. }
  984.  
  985. - copyAsPostScript:sender
  986. {
  987.     const char  *const types[1] = {NXPostScriptPboardType};
  988.  
  989.     [self deselectAll:self];
  990.     [[Pasteboard new] declareTypes:types num:1 owner:nil];
  991.     [self writePSCodeInside:&bounds to:[Pasteboard new]];
  992.   return self;
  993. }
  994.  
  995. - cut:sender
  996. {
  997.     [self copy:sender];
  998.     [self deleteGraphic:sender];
  999.     return self;
  1000. }
  1001.  
  1002. - paste:sender
  1003. {
  1004.     return [self paste:sender:NO]; // no centering
  1005. }
  1006.  
  1007. -paste:sender:(BOOL)flag
  1008. {
  1009.     char  **type;
  1010.     id      pb = [Pasteboard new];
  1011.     char   *data;
  1012.     int     length;
  1013.  
  1014.     for(type = [pb types];*type;type++) {
  1015.         if(!strcmp(*type,"PencilPBoardType"))
  1016.             break;
  1017.     }
  1018.     if(*type) {
  1019.                 char *name; NXColor c1; NXColor c2; float lw; char *dm, *fm, *sm, *ud;
  1020.  
  1021.                 IFCUR
  1022.                 {
  1023.                     NXRect rec;
  1024.  
  1025.                     [CUR calculateBoundingBox:self];
  1026.                     [CUR giveBounds:&rec];
  1027.                     [CUR select:NO];
  1028.                     CUR=nil;
  1029.                     curGrPos=-1;
  1030.                     [self display:&rec:1];
  1031.                     [self lockFocus]; PSnewinstance(); [self unlockFocus];
  1032.                 }
  1033.  
  1034.         [pb readType:*type data:&data length:&length];
  1035.          currentGraphic =NXReadObjectFromBuffer(data, length);
  1036.     if([CUR isMemberOf:[MultipleSelection class]])
  1037.         [CUR addElementsTo:glist];
  1038.     else
  1039.         [glist addObject:CUR];
  1040.     NXFreeObjectBuffer(data, length);
  1041.     if(flag)
  1042.     {
  1043.         NXPoint c;
  1044.         
  1045.         [window getMouseLocation:&c];
  1046.         [self convertPoint:&c fromView:nil];
  1047.         [CUR centerAt:&c];
  1048.     }
  1049.     else
  1050.         [currentGraphic addTranslation:-10:-10];
  1051.     curGrPos=[glist count]-1;
  1052.         [CUR select:YES];
  1053.                 [self lockFocus];
  1054.                 PSsetinstance(YES);
  1055.                 PSnewinstance();
  1056.                 [currentGraphic drawControl:NULL:curPt:500/scale];
  1057.                 [CUR giveSettings:&name:&c1:&c2:&lw:&dm:&fm:&sm:&ud];
  1058.                 [inspector takeSettings:name:c1:c2:lw:dm:fm:sm:ud];
  1059.                 PSsetinstance(NO);
  1060.                 [self unlockFocus];
  1061.         EDITED;
  1062.     }
  1063.     return self;
  1064. }
  1065.  
  1066. - sendCustom
  1067. {
  1068.     [self lockFocus];
  1069.     DPSPrintf(DPSGetCurrentContext(), " %s\n ", customDef);
  1070.     [self unlockFocus];
  1071.     return self;
  1072. }
  1073.  
  1074. - takeCustomFrom:(id)text
  1075. {
  1076.     if(customDef) free(customDef);
  1077.     customDef=(char *)malloc(sizeof(char)*([text textLength]+1));
  1078.     [text getSubstring:customDef start:0 length:[text textLength]+1];
  1079.     [self sendCustom];
  1080.     [self display];
  1081.     EDITED;
  1082.     return self;
  1083. }
  1084.  
  1085. - giveCustomTo:(id)text
  1086. {
  1087.     [text setText:(const char *)customDef];
  1088.     return self;
  1089. }
  1090.  
  1091. - importImage:sender
  1092. {
  1093.     const char *types[]={ "tiff", "eps", "rib", NULL };
  1094.  
  1095.     if([[OpenPanel new] runModalForTypes:types]==NX_OKTAG)
  1096.     {
  1097.         [self importImageFromFile:[[OpenPanel new] filename]:bounds.origin.x+5:bounds.origin.y+5];
  1098.         [self displayCurrentGraphic];
  1099.     }
  1100.     return self;
  1101. }
  1102.  
  1103. - importImageFromFile:(char *)name:(float)posx:(float)posy
  1104. {
  1105.         char *mname; NXColor c1; NXColor c2; float lw; char *dm; char *fm; char *sm; char *ud;
  1106.         [self deselectAll:self];
  1107.         [inspector giveSettings:&mname:&c1:&c2:&lw:&dm:&fm:&sm:&ud];
  1108.         if(CUR=[[PencilImage alloc] initFromFile:name])
  1109.         {
  1110.             curGrPos=[glist count];
  1111.             [glist addObject:CUR];
  1112.             [CUR select:YES];
  1113.             [CUR initWithSettings:mname:c1:c2:lw:dm:fm:sm:ud];
  1114.             [CUR addTranslation:posx:posy];
  1115.             [CUR calculateBoundingBox:self];
  1116.             EDITED;
  1117.         }
  1118.         return self;
  1119. }
  1120.  
  1121. - richTextEnded:sender
  1122. {
  1123.     editingRichText=NO;
  1124.     [flippedView removeFromSuperview];
  1125.     return self;
  1126. }
  1127.  
  1128. - convertToCharPath:sender
  1129. {
  1130.     IFCUR {
  1131.         // is it a RichText?
  1132.         if([currentGraphic isKindOf:[PencilText class]])
  1133.         {
  1134.         id newtxt;
  1135.         char *mname; NXColor c1; NXColor c2; float lw; char *dm, *fm, *sm, *ud;
  1136.         
  1137.         EDITED;
  1138.         newtxt=[[PencilGraphic alloc] init];
  1139.         [CUR makeCharacterPath: self: newtxt]; // RichTxt will initialize CharP
  1140.         [glist addObject:newtxt];
  1141.         [self deleteGraphic:self];
  1142.         CUR=newtxt;
  1143.         curGrPos=[glist count]-2;
  1144.         [CUR select:YES];
  1145.         [self displayWithCurrentGraphic];
  1146.         {
  1147.                 [CUR giveSettings:&mname:&c1:&c2:&lw:&dm:&fm:&sm:&ud];
  1148.                 [inspector takeSettings:mname:c1:c2:lw:dm:fm:sm:ud];
  1149.         }
  1150.         }
  1151.     }
  1152.     return self;
  1153. }
  1154.  
  1155. - (char *)performCommand:(const char *)cmd
  1156. {
  1157.     static char resStr[20];
  1158.     int which=0;
  1159.     
  1160.     EDITED;
  1161.     if(!strcmp(cmd,"objectcount")) { sprintf(resStr, "%d", [glist count]); return resStr; }
  1162.     if(!strncmp(cmd,"getobject",9)) { 
  1163.         int num;
  1164.         sscanf(cmd,"%*s %d", &num);
  1165.         if(num>=0 && num<[glist count])
  1166.         {
  1167.             return [[glist objectAt:num] giveDescription];        }
  1168.     }
  1169.     if(!strncmp(cmd,"changeobject",12)) which=1; else if(!strncmp(cmd,"addobject",9)) which=2;
  1170.     
  1171.     if(which)
  1172.     {
  1173.         int type, num;
  1174.         if(result) NXCloseMemory(result, NX_TRUNCATEBUFFER);
  1175.         result=NXOpenMemory(cmd, strlen(cmd), NX_READONLY);
  1176.         if(which==2) NXScanf(result, "addobject %d",&type);
  1177.         else
  1178.             NXScanf(result, "changeobject %d %d",&num, &type);
  1179.         [self deselectAll:self];
  1180.         if(which==2)
  1181.         {
  1182.         switch(type)
  1183.         {
  1184.             case 0: CUR=[PencilGraphic alloc]; break;
  1185.             case 1: CUR=[PencilText alloc]; break;
  1186.         }
  1187.         }
  1188.         else
  1189.             if(num>=0 && num<[glist count])
  1190.                 CUR=[glist objectAt:num];
  1191.         IFCUR
  1192.         {
  1193.             [CUR initFromDescription:result];
  1194.             curGrPos=[glist count];
  1195.             if(which==2) [glist addObject:CUR];
  1196.             [CUR calculateBoundingBox:self];
  1197.             CUR=nil;
  1198.             sprintf(resStr, "%d", curGrPos);
  1199.             curGrPos=-1;
  1200.             return resStr;
  1201.         }
  1202.     }
  1203.     if(!strcmp(cmd, "display")) {
  1204.         [self displayWithCurrentGraphic];
  1205.         return "1";
  1206.     }
  1207.     if(!strncmp(cmd, "resize", 6)) {
  1208.         NXRect f;
  1209.         sscanf(cmd, "resize %f %f %f %f", &f.origin.x, &f.origin.y, &f.size.width, &f.size.height);
  1210.         [window placeWindowAndDisplay:&f];
  1211.         return "1";
  1212.     }
  1213.     if(!strncmp(cmd, "save", 4)) {
  1214.         char name[400];
  1215.         sscanf(cmd, "save %s", name);
  1216.         [self doSave:name];
  1217.         return "1";
  1218.     }
  1219.     if(!strcmp(cmd, "selection")) {
  1220.     int len;
  1221.     int maxlen;
  1222.     char *buf;
  1223.      
  1224.     if(result) NXCloseMemory(result, NX_TRUNCATEBUFFER);
  1225.     result=NXOpenMemory(NULL,0,NX_WRITEONLY);
  1226.     IFCUR {
  1227.         if([CUR isMemberOf:[MultipleSelection class]]) {
  1228.             id slist;
  1229.             int i;
  1230.             
  1231.             slist=[CUR slist];
  1232.             for(i=0;i<[slist count];i++) {
  1233.                 NXPrintf(result, "%d ", [glist indexOf:[slist objectAt:i]]);
  1234.             }
  1235.         } else {
  1236.         NXPrintf(result, "%d", curGrPos);
  1237.         }
  1238.     }
  1239.     else
  1240.         NXPrintf(result, "");
  1241.     NXGetMemoryBuffer(result, &buf, &len, &maxlen);
  1242.     return buf;
  1243.     }
  1244.     if(!strncmp(cmd, "delete", 6)) {
  1245.         int num;
  1246.         
  1247.         sscanf(cmd, "delete %d", &num);
  1248.         [self deselectAll:self];
  1249.         [glist removeObjectAt:num];
  1250.         return "1";
  1251.     }
  1252.     if(!strcmp(cmd, "print")) {
  1253.         [self printPSCode:self];
  1254.         return "1";
  1255.     }
  1256.     if(!strcmp(cmd, "name")) {
  1257.         if(docname)
  1258.             return docname;
  1259.         else
  1260.             return "";
  1261.     }
  1262.     if(!strncmp(cmd,"move",4)) {
  1263.         float dx, dy;
  1264.         
  1265.         sscanf(cmd, "move %f %f", &dx, &dy);
  1266.         [self translate:dx:dy];
  1267.         return "1";
  1268.     }
  1269.     if(!strncmp(cmd,"scale",5)) {
  1270.         float dx;
  1271.         
  1272.         sscanf(cmd, "scale %f", &dx);
  1273.         [self scale:dx/scale:dx/scale];
  1274.         scale=dx;
  1275.         return "1";
  1276.     }
  1277.     if(!strcmp(cmd,"paste")) {
  1278.         [self paste:self];
  1279.         return "1";
  1280.     }
  1281.     if(!strncmp(cmd, "select1",7)) {
  1282.         int i;
  1283.     
  1284.         sscanf(cmd, "select1 %d", &i);
  1285.         IFCUR { [CUR select:NO]; CUR=nil; curGrPos=-1; }
  1286.         if(i>=0 && i<[glist count])    { [CUR=[glist objectAt:i] select:YES]; curGrPos=i; }
  1287.         return "1";
  1288.     }
  1289.     if(!strncmp(cmd, "select",6)) {
  1290.     int  i, c=[glist count];
  1291.  
  1292.     if(result) NXCloseMemory(result, NX_TRUNCATEBUFFER);
  1293.     result=NXOpenMemory(cmd, strlen(cmd), NX_READONLY);
  1294.  
  1295.     NXScanf(result, "select");
  1296.     IFCUR { [CUR select:NO]; CUR=nil; curGrPos=-1; }
  1297.     while(NXScanf(result, " %d", &i)==1)    {
  1298.         if(i>=0 && i<c)
  1299.         {
  1300.         IFCUR { [CUR addToSelection:[[glist objectAt:i] select:YES] posFromEnd:0]; }
  1301.         else
  1302.         {    [CUR=[MultipleSelection alloc] initWithGraphic:[[glist objectAt:i] select:YES]];  }
  1303.         }
  1304.     }
  1305.     [CUR calculateBoundingBox:self];
  1306.     return "1";
  1307.     }
  1308.     if(!strcmp(cmd, "group")) {
  1309.         [self makeGroup];
  1310.         [CUR setGroupType:PENCIL_STANDARD_GROUP];
  1311.         return "1";
  1312.     }
  1313.     if(!strcmp(cmd, "ungroup")) {
  1314.         [self ungroup];
  1315.         return "1";
  1316.     }
  1317.     if(!strcmp(cmd,"clipgroup")) {
  1318.         [self makeClipGroup:self];
  1319.         return "1";
  1320.     }
  1321.     if(!strcmp(cmd, "front")) {
  1322.         [self toFront:self];
  1323.         return "1";
  1324.     }
  1325.     if(!strcmp(cmd, "back")) {
  1326.         [self toBack:self];
  1327.         return "1";
  1328.     }
  1329.     if(!strcmp(cmd, "copyPS")) {
  1330.         [self copyAsPostScript:self];
  1331.         return "1";
  1332.     }
  1333.     if(!strncmp(cmd, "import",6)) {
  1334.         char name[400];
  1335.         float x,y;
  1336.         
  1337.         sscanf(cmd, "import %s %f %f", name, &x, &y);
  1338.         [self importImageFromFile:name:x:y];
  1339.         return "1";
  1340.     }
  1341.     return "failed";
  1342. }
  1343. @end
  1344.